﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using AvalonDock;
using Dispatcher.Extensions;
using Dispatcher.Helpers;
using DataGrid = System.Windows.Controls.DataGrid;
using DragEventArgs = System.Windows.DragEventArgs;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MessageBox = System.Windows.MessageBox;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;

namespace Dispatcher.Views
{
    /// <summary>
    /// Interaction logic for TypeView.xaml
    /// </summary>
    public partial class CommonListView
    {
        /// <summary>
        /// Scroll timer.
        /// </summary>
        private readonly Timer _scrollTimer = new Timer();

        /// <summary>
        /// Refresh timer.
        /// </summary>
        private readonly Timer _refreshTimer = new Timer();

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="CommonListView"/> class.
        /// </summary>
        public CommonListView()
        {
            InitializeComponent();
            ColumnPropertyRelation = new Dictionary<DataGridColumn, DataGridAutoGeneratingColumnEventArgs>();
            ModelValueViewRelation = new Dictionary<object, DockableContent>();
            DragDropHelper = new ListViewDragDropHelper(this);
            DetailsHelper = new ListViewDetailsHelper(this);
            ColumnsHelper = new ListViewColumnsHelper(this);
            _refreshTimer.Interval = 100;
            _refreshTimer.Tick += (sender, args) =>
                                      {
                                          if (IsNeedRefresh)
                                          {
                                              ItemsDataGrid.RefreshDataGridRows();
                                          }

                                          IsNeedRefresh = false;
                                      };

            _refreshTimer.Enabled = true;

            LazyLoader.Loaded += (sender, args) => { IsNeedRefresh = true; };

            _scrollTimer = new Timer();
            _scrollTimer.Tick += (sender, args) =>
                              {
                                  LazyLoader.AddToLoad(ItemsDataGrid.GetVisibleRowItems());
                                  _scrollTimer.Enabled = false;
                              };
            _scrollTimer.Interval = 500;
            _scrollTimer.Enabled = true;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets a value indicating whether this instance is need refresh.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is need refresh; otherwise, <c>false</c>.
        /// </value>
        public bool IsNeedRefresh { get; set; }

        /// <summary>
        /// Gets the column property relation.
        /// </summary>
        public Dictionary<DataGridColumn, DataGridAutoGeneratingColumnEventArgs> ColumnPropertyRelation { get; private set; }

        /// <summary>
        /// Gets the model value view relation.
        /// </summary>
        public Dictionary<object, DockableContent> ModelValueViewRelation { get; private set; }

        /// <summary>
        /// Gets or sets the drag drop helper.
        /// </summary>
        /// <value>
        /// The drag drop helper.
        /// </value>
        private ListViewDragDropHelper DragDropHelper { get; set; }

        /// <summary>
        /// Gets or sets the details helper.
        /// </summary>
        /// <value>
        /// The details helper.
        /// </value>
        private ListViewDetailsHelper DetailsHelper { get; set; }

        /// <summary>
        /// Gets or sets the columns helper.
        /// </summary>
        /// <value>
        /// The columns helper.
        /// </value>
        private ListViewColumnsHelper ColumnsHelper { get; set; }

        /// <summary>
        /// Gets or sets the last mouse position.
        /// </summary>
        /// <value>
        /// The last mouse position.
        /// </value>
        private Point LastMousePosition { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is data grid edit mode.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is data grid edit mode; otherwise, <c>false</c>.
        /// </value>
        private bool IsDataGridEditMode { get; set; }

        #endregion

        #region Methods

        /// <summary>
        /// Called when [save changes executed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="Dispatcher.Helpers.ExtendedEventArgs"/> instance containing the event data.</param>
        public void OnSaveChangesExecuted(object sender, ExtendedEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            dataGrid.RefreshDataGridRows();

            if (e.HasException)
            {
                MessageBox.Show(e.Exception.Message + Environment.NewLine + e.Exception.InnerException.Message);
            }
            else
            {
                MainWindow.Instance.Status.Content = "Saved";
            }
        }

        /// <summary>
        /// Called when [undo changes executed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="Dispatcher.Helpers.ExtendedEventArgs"/> instance containing the event data.</param>
        public void OnUndoChangesExecuted(object sender, ExtendedEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            dataGrid.RefreshDataGridRows();
        }

        /// <summary>
        /// Handles the PreviewKeyDown event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            if (e.Key == Key.Enter)
            {
                dataGrid.CommitEdit();
            }
        }

        /// <summary>
        /// Handles the KeyDown event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_KeyDown(object sender, KeyEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            if (dataGrid.CurrentCell.Column.DisplayIndex == 4)
            {
                dataGrid.BeginEdit();
            }
        }

        /// <summary>
        /// Handles the CellEditEnding event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.DataGridCellEditEndingEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
        {
            IsDataGridEditMode = false;
            e.Row.BindingGroup.UpdateSources();
            DataGridExtensions.RefreshDataGridRow(e.Row);
        }

        /// <summary>
        /// Handles the BeginningEdit event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.DataGridBeginningEditEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
        {
            IsDataGridEditMode = true;
        }

        /// <summary>
        /// Handles the MouseMove event of the DocumentContent control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            var position = e.GetPosition(dataGrid);

            if (e.LeftButton == MouseButtonState.Pressed && 
                (Keyboard.Modifiers == ModifierKeys.Control || Keyboard.Modifiers == ModifierKeys.Shift))
            {
                if (!IsDataGridEditMode && e.OriginalSource.GetType() == typeof(TextBlock) &&
                (position.X.Equals(LastMousePosition.X) || position.Y.Equals(LastMousePosition.Y)))
                {
                    DragDropHelper.Drag();              
                }

                e.Handled = true;
                ItemsDataGrid.CancelEdit();
            }

            LastMousePosition = position;
        }

        /// <summary>
        /// Handles the Drop event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.DragEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_Drop(object sender, DragEventArgs e)
        {
            DragDropHelper.Drop(e);
            var dataGrid = (DataGrid)sender;
            dataGrid.RefreshDataGridRows();
        }

        /// <summary>
        /// Handles the AutoGeneratingColumn event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.DataGridAutoGeneratingColumnEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            ColumnsHelper.GenerateColumn(dataGrid, e);
        }

        /// <summary>
        /// Handles the MouseDoubleClick event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var dataGrid = (DataGrid)sender;
            DetailsHelper.TryShowDetails(dataGrid);
        }

        /// <summary>
        /// Handles the ScrollChanged event of the ItemsDataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.ScrollChangedEventArgs"/> instance containing the event data.</param>
        private void ItemsDataGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            _scrollTimer.Enabled = false;
            _scrollTimer.Interval = 70;
            _scrollTimer.Enabled = true;
        }

        #endregion
    }
}
